﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Domino;
using WcfMail.Interface;
using System.IO;

namespace Hisuntech.SystemFramework.Net.Mail
{
    public class LotusNotes : Emails
    {
        NotesSession ns;
        NotesDatabase ndb;

        public LotusNotes()
        {
           
        }

        public override  MailServerInfo SMTP_Server
        {
            get
            {
                return MailConfig.GetConfig(MailServerType.Notes);
            }
            set
            {
                base.SMTP_Server = value;
            }
        }

        /// <summary>
        /// 初始化配置
        /// </summary>
        private void InitConfig()
        {
            if (ns == null)
            {
                //初始化NotesSession
                ns = new NotesSession();
                ns.Initialize(this.POP3_Server.ServerPassword);//"q1w2e3r4"

                //初始化NotesDatabase
                //注意：本程序请勿长时间维持一个实例，这可能导致Notes的数据保持在打开状态，
                //      如果此时有其它用户（例如多线程或者多进程）访问邮件账户，会出现“数据库无法共享”的错误。
                ndb = ns.GetDatabase(this.POP3_Server.MailServer, this.POP3_Server.ServerUsername, false);//"cs.9fbank.cn/9fbank" ,"mail\\hdeng.nsf"
                //这里也可以使用用户的数据库文件 mail\\hdeng.nsf 
                //如果使用names.nsf，则无法向系统外部发送邮件 
                //使用下面的方式可能无法对外发送邮件
                //NotesDbDirectory dir = ns.GetDbDirectory("");
                //ndb = dir.OpenMailDatabase();
            }
        }

        public override bool Send(ISysMsg message)
        {
            ErrorMessage = "";
            MailMessageInfo mailInfo = (MailMessageInfo)message;
            try
            {
                InitConfig();
                if (ns != null)
                {
                    NotesDocument doc = ndb.CreateDocument();
                    
                    doc.ReplaceItemValue("Form", "Memo");
                    //收件人信息
                    doc.ReplaceItemValue("SendTo", mailInfo.MailTo );
                    /*
                    如果想发送给多个联系人，可以按如下代码编写：
                    string[] receivers = { cb_People.SelectedItem.ToString(), "windie chai/TEST" };
                    doc.ReplaceItemValue("SendTo", receivers);
                    */
                    //邮件主题
                    doc.ReplaceItemValue("Subject", mailInfo.MsgSubject );
                    //邮件正文

                    NotesRichTextItem rt = doc.CreateRichTextItem("Body");
                    //采用下面的方式邮件中会加入回车符号？？？
                    rt.AppendText(mailInfo.MsgContent);
                    //采用下面的方式正文超过100K 对外无法发送邮件？
                    //doc.ReplaceItemValue("Body", mailInfo.MsgContent);

                    //回执要求
                    //测试表明，NOTES对外部邮件系统发送邮件，无法添加自定义的邮件头，下面的方法无效
                    //doc.AppendItemValue ("ReturnReceipt", "1");
                    //doc.AppendItemValue("Disposition-Notification-To", mailInfo.MailFrom);
                    
                   
                    //附件
                    if (mailInfo.AttachmentFiles!=null)
                    {
                        foreach (string file in mailInfo.AttachmentFiles)
                        {
                            NotesRichTextItem attachment = doc.CreateRichTextItem("attachment");
                            attachment.EmbedObject(EMBED_TYPE.EMBED_ATTACHMENT, "", file, "attachment");
                        }
                    }
                    //发送邮件
                    object obj = doc.GetItemValue("SendTo");
                    doc.Send(false, ref obj);

                    doc = null;
                    return true;
                }
            }
            catch (Exception ex)
            {
                this.ErrorMessage = ex.Message;
            }
            return false;
        }

        /// <summary>
        /// 接收多封邮件到邮件消息队列,如果成功，请检查message.MsgContent的值获取收到的邮件数
        /// </summary>
        /// <param name="message">邮件服务器信息</param>
        /// <param name="delMail">接收完成以后是否全部删除服务器上面的邮件</param>
        /// <param name="delMsgID">如果不全部删除，指定要删除的邮件序号（从1开始）</param>
        /// <returns>操作是否成功</returns>
        public override bool Receive(ISysMsg message, bool delMail, int delMsgID)
        {
            this.ReceiveInit();
            int success = 0;
            //int fail = 0;
            //是否需要匹配邮件标题
            bool needMatching = !string.IsNullOrEmpty(this.MatchingTitle);
            System.Diagnostics.Debug.WriteLine("开始检查邮件");

            try
            {
                InitConfig();
                if (ndb != null)
                {
                    NotesView nv = ndb.GetView("$inbox");
                    //从新往旧遍历所有邮件
                    NotesDocument doc = nv.GetLastDocument();
                    NotesDocument tempDoc = null;
                    int i = 1;
                    DateTime mailDate = DateTime.Now.AddDays(-1);
                    while (doc != null)
                    {
                        MailMessageInfo mail = new MailMessageInfo();
                        mail.MsgSubject = ((object[])doc.GetItemValue("Subject"))[0].ToString();
                        mail.MailFrom = ((object[])doc.GetItemValue("From"))[0].ToString();
                        //采用 GetItemValue 方式获取正文当大小超过150K左右有可能接收不全，所以采用 GetFirstItem 方式
                        //mail.MsgContent  = ((object[])doc.GetItemValue("Body"))[0].ToString();
                        NotesItem itemBody = doc.GetFirstItem("Body");
                        mail.MsgContent =itemBody==null?"": itemBody.Text;

                        //处理回执标志
                        //虽然NOTES无法对外发送回执标记，但可以处理外部邮件系统要求的回执标记
                        object objTemp = doc.GetItemValue("ReturnReceipt");
                        if (objTemp != null)
                        {
                            string flag = ((object[])objTemp)[0].ToString();
                            if (flag == "1")
                                this.ReturnReceipt.Add(mail.MsgSubject);
                        }

                        message.MsgSubject = "No." + i + ":" + mail.MsgSubject;
                        this.Receiving(message);


                        if (DateTime.TryParse(((object[])doc.GetItemValue("PostedDate"))[0].ToString(), out mailDate))
                        {
                            mail.Time = mailDate;
                            System.Diagnostics.Debug.WriteLine("Post Date:" + mail.Time.ToString());
                            string mailUser = this.POP3_Server.ServerUsername;

                            if (!this.IsNewMail(mailDate, mailUser, i))
                                break;
                        }
                        else
                        {
                            this.ErrorMessage = "不可识别的日期内容：";
                        }
                        //先判断邮件日期，在收取邮件内容
                        if (!needMatching ||
                           (needMatching && mail.MsgSubject.StartsWith(this.MatchingTitle))
                           )
                        {
                            success++;
                            mail.MessageID = i;
                            //Notes 邮件可能在邮件正文中插入额外的回车换行符
                            if (message.MsgType == WcfMail.SystemConst.WCF_MAIL_FLAG)
                            {
                                mail.MsgContent = mail.MsgContent.Replace("\r\n", "");
                            }

                            object[] items = (object[])doc.Items;
                            //处理附件
                            string strTime = DateTime.Now.ToString("yyyyMMddhhmmss");

                            foreach (NotesItem item in items)
                            {
                                if (item.Name == "$FILE")
                                {
                                    string fileName = ((object[])item.Values)[0].ToString();
                                    NotesEmbeddedObject file = (NotesEmbeddedObject)doc.GetAttachment(fileName);
                                    if (file != null)
                                    {
                                        //必须使用原始文件名，或者程序处理起来会有问题
                                        //string realFileName = base.AttachmentPath + "/" + strTime + "No" + (i) + "_" + file.Name;
                                        string realFileName = base.AttachmentPath + "/" + file.Name;
                                        file.ExtractFile(realFileName);
                                        //必须记录文件的全路径
                                        mail.AddAttachment(realFileName);
                                    }
                                }
                            }
                            //加入消息队列
                            this.MessageQueue.Add(mail);
                            this.Received(mail);
                            this.CurrentMailInfo = mail;

                            if (this.ReceiveAndDelete)
                            {
                                //doc.Remove(true);//此时删除邮件会导致下面的遍历邮件操作失败
                                tempDoc = doc;
                            }
                        }
                        else
                        {
                            //不匹配的邮件
                        }
                        //删除当前邮件
                        if (i == delMsgID && delMsgID > 0 && !this.ReceiveAndDelete)
                        {
                            //doc.Remove(true);//此时删除邮件会导致下面的遍历邮件操作失败
                            tempDoc = doc;
                        }


                        //查找下一封邮件
                        doc = nv.GetPrevDocument(doc);
                        if (tempDoc != null)
                        {
                            tempDoc.Remove(true);
                            tempDoc = null;
                        }
                        i++;

                        if (success > CHECK_MAIL_MAX_COUNT)
                            break;
                    }//end while
                    //Notes 的特殊处理
                    //this.IsNewMail(mailDate, this.POP3_Server.ServerUsername, 0);
                    //Notes 不提供删除所有邮件的方法
                    //if (delMail)
                    //{
                    //}
                   
                }
                else
                {
                    this.ErrorMessage = "获取本地数据库失败，请检查NOTES配置。";
                    return false;
                }
            }
            catch (Exception ex)
            {
                this.ErrorMessage = "接收邮件异常：\r\n"+ex.Message+"\r\n"+ex.StackTrace;
                return false;
            }
           
           
            System.Diagnostics.Debug.WriteLine("检查结束");
            message.MsgContent = success.ToString();
            return true;
        }


    }
}